package com.niyue.sandbox.invokevis;

import java.util.Stack;

import org.aspectj.lang.Signature;

import com.niyue.sandbox.invokevis.util.IvConfig;

import java.util.List;

import com.niyue.sandbox.invokevis.util.FileUtil;
public abstract aspect MethodInvocation {
	private Stack<TreeNode> callStack = new Stack<TreeNode>();
	private boolean start = false;
	//private int invokeDepth = Integer.parseInt(IvConfig.getValue(IvConfig.INVOKE_DEPTH));
	abstract pointcut entrypoint();
	
//	void around(): entrypoint(){
//		Signature methodSignature = thisJoinPointStaticPart.getSignature();
//		TreeNode rootNode = new TreeNodeImpl(methodSignature.toShortString(), 0);
//		callStack.push(rootNode);
//		start = true;
//		proceed();
//		start = false;
//		rootNode = callStack.pop();
//		MethodInvocationStatus.setRootNode(rootNode);	
//		// output to different format according to configuration
//		String format = IvConfig.getValue(IvConfig.OUTPUT_FORMAT);
//		if(format.equals("html")){
//			FileUtil.writeContent("out/iv.html", rootNode.toHtml());
//		}
//		else if(format.equals("dot")){
//			FileUtil.writeContent("out/iv.dot", rootNode.toDot());
//		}
//		else{
//			FileUtil.writeContent("out/iv.txt", rootNode.toPlainText());
//		}
//	}

	before(): entrypoint(){
		Signature methodSignature = thisJoinPointStaticPart.getSignature();
		TreeNode rootNode = new TreeNodeImpl(methodSignature.toShortString(), 0);
		callStack.push(rootNode);
		start = true;
		System.out.println("[INVOKEVIS]: Entering entrypoint...");
	}
	after(): entrypoint(){
		System.out.println("[INVOKEVIS]: Leaving entrypoint...");
		start = false;
		TreeNode rootNode = callStack.pop();
		MethodInvocationStatus.setRootNode(rootNode);	
		// output to different format according to configuration
		String format = IvConfig.getValue(IvConfig.OUTPUT_FORMAT);
		List formatList = IvConfig.parseFormat(format);
		if(formatList.contains("html")){
			FileUtil.writeContent("iv.html", rootNode.toHtml());
		}
		if(formatList.contains("dot")){
			FileUtil.writeContent("iv.dot", rootNode.toDot());
		}
		if(formatList.contains("xml")){
			FileUtil.writeContent("iv.xml", rootNode.toXml());
		}
		if(formatList.contains("txt")){
			FileUtil.writeContent("iv.txt", rootNode.toPlainText());
		}
	}

	abstract pointcut invokepoint();

	before(): invokepoint(){
		Signature methodSignature = thisJoinPointStaticPart.getSignature();
		if(start){
			TreeNode parentNode = (TreeNode) callStack.peek();
//			if(invokeDepth > parentNode.getLevel() || invokeDepth ==0){
				TreeNode childNode = new TreeNodeImpl(methodSignature.toShortString(), parentNode.getLevel() + 1);
				parentNode.addChild(childNode);
				callStack.push(childNode);
//			}
		}
	}
	after(): invokepoint(){
		if(start){
			/*
			if(callStack.size() == 2){
				Signature methodSignature = thisJoinPointStaticPart.getSignature();
				System.out.println("Size == 2:" + methodSignature.toString());
				System.out.println(callStack.peek().getMethodName());
			}
			if(callStack.size() == 1){
				Signature methodSignature = thisJoinPointStaticPart.getSignature();
				System.out.println("Size == 1:" + methodSignature.toString());
			}
			if(callStack.isEmpty()){
				Signature methodSignature = thisJoinPointStaticPart.getSignature();
				System.out.println(methodSignature.toString());
			}
			*/
			callStack.peek();
			//TreeNode parentNode = (TreeNode) callStack.peek();
//			if(invokeDepth > parentNode.getLevel() || invokeDepth ==0){
				callStack.pop();
//			}
		}
	}
}
